
import { SHA256, enc } from 'crypto-js'
import JSEncrypt from 'jsencrypt'

import { GenerateRSAKeys_to_B64 } from './lib'
const envObj = import.meta.env



class RSACryptoTool {
  pubk: string
  #prik: string

  rsaInstance = new JSEncrypt({ log: envObj.DEV })


  /**
   * 
   * @param k the pem encoded string or an object (with or without header/footer)
   * @returns 
   */
  constructor(k?: string) {
    if (!k) {
      this.pubk = ''
      this.#prik = ''
      return
    }

    this.rsaInstance.setKey(k)
    const pemPubk_b64 = this.rsaInstance.getPublicKeyB64()
    this.pubk = pemPubk_b64

    const pemPrik_b64 = this.rsaInstance.getPrivateKeyB64()
    this.#prik = pemPrik_b64

  }

  /**
   * 生成key的方法,
   */
  async Init() {
    const keys = await GenerateRSAKeys_to_B64()
    this.pubk = keys.pubk_b64
    this.#prik = keys.prik_b64
    this.rsaInstance.setPrivateKey(keys.prik_b64)
  }

  /**
   * 
   * @param  content 要加密的内容字符串
   * @param  pubk 公钥
   */
  encrypto(content: any, pubk?: string) {
    const tc = typeof content === 'object' ? JSON.stringify(content) : content.toString()
    if (pubk) {
      const ec = new JSEncrypt({ log: envObj.DEV })
      ec.setKey(pubk)
      return ec.encrypt(content)
    }
    return this.rsaInstance.encrypt(tc)

  }
  /**
   * 解密
   * @param  ciphertext 密文
   * @param  prik 私钥
   * @returns 
   */
  decrypto(ciphertext: string | false, prik?: string) {
    if (!ciphertext) return ciphertext
    if (prik) {
      const dc = new JSEncrypt({ log: envObj.DEV })
      dc.setKey(prik)
      return dc.decrypt(ciphertext)
    }
    return this.rsaInstance.decrypt(ciphertext)

  }
  verify(sign: string, text: string, pubk: string) {
    const jSEncrypt = new JSEncrypt()
    jSEncrypt.setPublicKey(pubk)
    // CryptoJS.SHA256(s).toString(enc.Base64)
    return jSEncrypt.verify(text, sign, (s) => SHA256(s).toString())
  }
  sign(text: string, prik: string = this.#prik) {
    const jSEncrypt = new JSEncrypt()
    jSEncrypt.setPrivateKey(prik)
    return jSEncrypt.sign(text, (s) => SHA256(s).toString(), 'sha256')
  }
}

class RSATester {
  // 1024 位,服务端公私钥测试样例
  serverPublicKey = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDDo2pKptHozEVwm3OIrwfz573XDOjoPQGzXweKu3eruNtSyL2mtZsFQDBy8hnQdvtA5aPZPhc4MAq9T5a81LSwzGLwWJhFgyJTvvanb/hVVAjP+8oKR8j9mZuSheMWyjxWG4iN7KBoRTuzepqXtiRfJvY836atwZVQ/gIGrlLPfQIDAQAB'
  serverPriviteKey = 'MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAMOjakqm0ejMRXCbc4ivB/PnvdcM6Og9AbNfB4q7d6u421LIvaa1mwVAMHLyGdB2+0Dlo9k+FzgwCr1PlrzUtLDMYvBYmEWDIlO+9qdv+FVUCM/7ygpHyP2Zm5KF4xbKPFYbiI3soGhFO7N6mpe2JF8m9jzfpq3BlVD+AgauUs99AgMBAAECgYAAj1xC1sbJYItb9bTPpZBsqxfvqbkPI/sWq5FfIB+5yM05oacjCWJH55c0Sx9ay0m6ZoS8SW9IxVeTq6w/MQgzqFqSaqgG8TKp9jtFzcrdW8z/AioyBIRyn2qzkn3tkq2eOvlFK9IvBqu+Ue7pX6Ym1D1UT2zET0Hh4DgGSvMS2wJBAPXtLlZItFfY1xcWMSkHszYoc+sFyCACmkoPqjYY0jSffHtwnai3iOlFxbFd1pvzhEi7kLtxvnAlab3EAHL2CYcCQQDLpuff+qmWhsZ03sGyxsXshnTMnSZP8vhOa/u81L01y3AIbDfyZEnm8trD0e0T81BHMBPEYb7XIyv2VIZp2E/bAkAaSUDDrj/AiAftisy0YwNPzaEeRN7wNPcC5Yu+/oYxY76tfwsLBpsWvAN2gt42ix/fmlTNBEpjuEwGIZYes5evAkAYiUt2mOTF1gcjHZOIzpoaHTkFTgnHqCZyjGAQKDGDwbcFzMQQ2DRvNuNUpH5D4RTS/t/i0UQE95/cVeK77evxAkBWs6Dp8P7bSRb4AdHbgeW3BuBH0mhUMSSeXf7tjZC5uBCU6ddj/af2zCGI68z/2HpKvYdjE6s7vsIobxsI5hc2'
  serverCiphertext = 'IvY8M5z/WcX5+S9bBtTV3FuHZRW54waKdQQUPQQXqHSwBMhS/HSzSaN0DHx1NHoa+bU+F8TxkRuGReOQiLWXEITnlbloTWwW7O4QPdq4+wPA6CHFUUbb49glLAprea9EEPUVfgyVfd26jThlqyf5jzxLpk14TiLuMkmedzPWruc='

  // 1024 位,前端生成公私钥测试样例
  staticPublicKey = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDEr3ZxJIf3Buqto/q1dDT9DKSdMP7a4z+JSZT5w9jKpNoag+V3GBcPqiGrfRUaQiJQBgR611BTFmqqKl2/vQNGMPmDkQL41B2h12OgFxtT1wKzB+HpqNgqFvN+azt+2/1ujTotGDQ2KnEEwuHXiJilIQz4/tdS2K0QqqkcFlbwAQIDAQAB'
  staticPriviteKey = 'MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAMSvdnEkh/cG6q2j+rV0NP0MpJ0w/trjP4lJlPnD2Mqk2hqD5XcYFw+qIat9FRpCIlAGBHrXUFMWaqoqXb+9A0Yw+YORAvjUHaHXY6AXG1PXArMH4emo2CoW835rO37b/W6NOi0YNDYqcQTC4deImKUhDPj+11LYrRCqqRwWVvABAgMBAAECgYAWeSb7JA2uDdoEN6OWlp3UWRy5AkdoesVAekodpMFRXDc4huAR9Mxzw4B/3/Woj6xsgNeDsrTwnXPYGCmolh/4soHK6w2FwjRmil+NHGN1wt8RkIGmopxi8Rx3wBQf68XQW2BiAIExKyheXGMwSE+0xPFnfy0CzOVMwdnJEqf4LQJBAPKpUYs8p6/BKIfw/I9utZQcd5tq91tbqYUqHADfIfuwFIvPiHADPgxLnIj7kUofnNchsKFtfFQCXBwJ2VfTjz0CQQDPfy3mV4PgTFiranxaloCyB5eY9/aGPF/V6mnoy/dGt9J9oF8+jkJip8c5CNtvhddWKRyaWe7uTQcqIwc1r/AVAkEAkLYOzhU2/yYW8LLzOupP2Or9HS82IkJQnvxUxORMVNdV+WajPAGDADwbNsmnhGfD1bvepPYw/byGh6YL+kdNFQJBAMT4MZYrFWDimHmASDOmEtztIBdxq2+Z+E+Uip0WodFbxlDC4Cb93D7SjeeyZLvlDZkYxbIwFQPZ0ydIwRtRvFECQQC9n/TLkiltOGUQEte+P6A+cbUcxWONh6ZBCJOR71uD3zmxQuClqypL4KfjGufPtxsRfFVvT803IGiEGoS3FDvj'
  staticCiphertext = 'xHtotow8SeNwHwybXo2DFvuIWVXRmnJPIv1fPyT+fpujOAOudis9Z9SUxmyAJlmdL0cmyyUQOM75E5SHdsqJnF4mM0fgo2tZT9mQD/WXoKGJmYoeqfwc8eXHMReLZ/oKyigEP7SqpkKB/Iq95bxq4b5QcHCw5oslesi8B8WqykM='
  // http://web.chacuo.net/netrsakeypair 网页生成公私钥对
  webToolGenerPubkey = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDRamCoffv+GbmZRH3JNmO2dvGuTDaRLb/rYBBgQoafdaqCeXve7LcxxwUjyQqKM0TtshPsd2gxYDyuayla/xEYn8K6euwqRu3npWqSXKqrTy6/fP2ONWjG73XAyc1qYwVmaMyec3ezcOFmc7KXdYLkAIFrIx4n+M7nujAA+zmO0wIDAQAB'
  webToolGenerPrvkey = 'MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBANFqYKh9+/4ZuZlEfck2Y7Z28a5MNpEtv+tgEGBChp91qoJ5e97stzHHBSPJCoozRO2yE+x3aDFgPK5rKVr/ERifwrp67CpG7eelapJcqqtPLr98/Y41aMbvdcDJzWpjBWZozJ5zd7Nw4WZzspd1guQAgWsjHif4zue6MAD7OY7TAgMBAAECgYBztge6kgJPIP/AhGvMZlUqWQapfEsaZOEKuYXS6m9gZK/WcDHVt45x3rokT82XF0Ua4a7IliHoRnjBF00+jnlu1bTltY32TuQESowxQYVCe6wXykM08Hpf+LeCYB93KEyJpp6oEphe+sH5WDRTI4HzjTB0bH86oIU+Eu5aJAXk4QJBAO88wuXlle/7N5YnYHF1X0aUFps8mJkxNOMZT5mQCG4K6bdAAi6dMC0tD29db7RvyY+RzRipSBEW1Yg7Q7gvblcCQQDgFrKYTupTpr0w0zADFdLbK+1atJuMGn9kKu8VlsY0LohvUfik4dqXxJlXbfzqEeTcTqXlN4vHtZexp/UJlB3lAkARbGZxYeAiozQwLlv6x2aR+FURJz+h4JCOfZhrga7rfMX6v6GpDW+lyqNWJALvrDiMyTybsDB8diJFErPi5SlvAkA5xMAv0ZBJFmAJeTgUY4jjJZTf4FWFLcOPkB3og+D+zMwxXoFqCCtxGqapSlp8ATbtsHzF9abcSi0cCH98A6odAkEAg2/+7aJzx4Ho1W6jAKuHwgc+9DDljMOOZCxJWgyE/IRL3idrovj8/SA22FhVWgwlHEAb66QVWVjZDBxxeugIRQ=='
  async begin() { return this }
  async GenerateTest() {
    console.log('=======================================================>');
    console.log('开始初始化加密工具:自己生成key测试');

    const rsaTool = new RSACryptoTool()
    const originalData = { name: '家铭', age: 12 }
    // const originalData = 123123123123
    console.log('开始生成公私钥对:',);
    await rsaTool.Init()
    console.log(rsaTool);
    const stringEcryptoResult = rsaTool.encrypto(originalData)
    console.log('字符串加密结果', stringEcryptoResult);
    console.log('开始解密对象....');
    const objDecryptoResult = rsaTool.decrypto(stringEcryptoResult)

    console.log('字符串密文解密结果:', objDecryptoResult);
    console.log('<=======================================================');
    return this
  }
  async ImportKeyTest() {
    console.log('=======================================================>');
    console.log('导入私钥,使用导入的私钥加解密测试');

    const rsaTool = new RSACryptoTool(this.staticPriviteKey)
    const originalData = { name: '家铭', age: 12 }

    console.log(rsaTool);
    const stringEcryptoResult = rsaTool.encrypto(originalData)
    console.log('字符串加密结果', stringEcryptoResult);
    console.log('开始解密对象....');
    const objDecryptoResult = rsaTool.decrypto(stringEcryptoResult)

    console.log('字符串密文解密结果:', objDecryptoResult);
    console.log('<=======================================================');
    return this
  }
  async CiphertextDecodeTest() {

    console.log('已有私钥,解密密文=======================================================>');
    console.log('已有私钥 ', this.staticPriviteKey);

    const rsaTool = new RSACryptoTool(this.staticPriviteKey)
    // const originalData = { name: '家铭', age: 12 }
    // const originalData = testInfo

    console.log(rsaTool);
    /* const stringEcryptoResult = rsaTool.encryptoByObj(originalData) */
    console.log('密文', this.staticCiphertext);
    console.log('开始解密对象....');
    const objDecryptoResult = rsaTool.decrypto(this.staticCiphertext)
    console.log('字符串密文解密结果:', objDecryptoResult);
    console.log('<=======================================================');
    return this
  }
  async verifyAndSign() {
    console.log('=======================================================>');
    console.log('签名和验签测试');
    const rsaTool = new RSACryptoTool(this.staticPriviteKey);
    const originalData = { name: '家铭', age: 12 };
    const sign = rsaTool.sign(JSON.stringify(originalData), this.staticPriviteKey);
    console.log('签名:', sign);
    const verifyed = rsaTool.verify(sign as string, JSON.stringify(originalData), this.staticPublicKey);
    console.log('验签是否通过', verifyed);

    console.log('<=======================================================');
    return this
  }

  async toolWebGenerKeyTestImport() {

    console.log('已有web工具生成私钥服务器公司钥测试=======================================================>');
    const rsaTool = new RSACryptoTool(this.webToolGenerPrvkey)
    const originalData = 123456768

    console.log('工具:', rsaTool, '源对象:', originalData);
    const stringEcryptoResult = rsaTool.encrypto(originalData)
    console.log('字符串加密结果', stringEcryptoResult);
    console.log('开始解密对象....');
    const objDecryptoResult = rsaTool.decrypto(stringEcryptoResult)

    console.log('字符串密文解密结果:', objDecryptoResult);
    console.log('<=======================================================');
    return this
  }
  async ServerPriviteKeyDecodeServerCiphertext() {

    console.log('已有服务器私钥,解密密文=======================================================>');
    console.log('已有私钥 ', this.serverPriviteKey);

    const rsaTool = new RSACryptoTool(this.serverPriviteKey)
    console.log(rsaTool);
    console.log('密文', this.serverCiphertext);
    console.log('开始解密对象....');
    const objDecryptoResult = rsaTool.decrypto(this.serverCiphertext)
    console.log('字符串密文解密结果:', objDecryptoResult);
    console.log('对比成功', '1234567890' === objDecryptoResult);

    console.log('<=======================================================');
    return this
  }

}


export {
  RSACryptoTool,
  RSATester,
}